package reflection;
import org.junit.Test;
import org.springframework.util.ReflectionUtils;
import reflection.generic.PrintLogChild1;
import reflection.generic.PrintLogChild2;
import sun.reflect.Reflection;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.stream.Collectors;

public class ReflectionTest {

	@Test
	public void testOverride() {
		ReflectionApplication reflectionApplication = new ReflectionApplication();
/*		reflectionApplication.age(16);
		reflectionApplication.age(Integer.valueOf(16));*/
	}

	@Test
	public void testReflection() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
		ReflectionApplication reflectionApplication = new ReflectionApplication();
		// 通过类的反射获取到的方法，不管传的是int还是Integer，执行的都是int参数的方法。
		ReflectionApplication.class.getDeclaredMethod("age",Integer.class).invoke(reflectionApplication, 15);
		ReflectionApplication.class.getDeclaredMethod("age",Integer.class).invoke(reflectionApplication, Integer.valueOf(15));

		ReflectionApplication.class.getDeclaredMethod("age",Integer.TYPE).invoke(reflectionApplication, 15);
		ReflectionApplication.class.getDeclaredMethod("age",Integer.TYPE).invoke(reflectionApplication, Integer.valueOf(15));
	}

	@Test
	public void testPrintLogChild1() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
		PrintLogChild1 child1 = new PrintLogChild1();
		//PrintLogChild1.class.getDeclaredMethod("printLog",String.class).invoke(child1,"test");

		Arrays.stream(child1.getClass().getMethods())
				.filter(method -> method.getName().equals("printLog"))
				.forEach(method -> {
					try {
						method.invoke(child1,"test1");
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					} catch (InvocationTargetException e) {
						e.printStackTrace();
					}
				});

		PrintLogChild2 child2 = new PrintLogChild2();
		Arrays.stream(child2.getClass().getMethods())
				.filter(method -> method.getName().equals("printLog"))
				.forEach(method -> {
					try {
						method.invoke(child2,"test1");
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					} catch (InvocationTargetException e) {
						e.printStackTrace();
					}
				});
		child2.getClass().getDeclaredMethod("printLog",String.class).invoke(child2,"test1");
	}

	@Test
	public void testBridgeMethod(){
		PrintLogChild2 child2 = new PrintLogChild2();
		child2.getClass().getDeclaredMethods();
		Arrays.stream(child2.getClass().getDeclaredMethods())
				.filter(method -> !method.isBridge())
				.collect(Collectors.toList());
	}

	@Test
	public void testReflection1() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException,
			InstantiationException {
		Class class1  =  Class.forName("reflection.ReflectionApplication");
		ReflectionApplication reflectionApplication = (ReflectionApplication) class1.newInstance();

		Method method = class1.getDeclaredMethod("age",Integer.class);
		// 如果方法是私有的，访问之前要设置Accessible(true)
		method.setAccessible(true);
		method.invoke(reflectionApplication, 15);
	}

}
